import { CrcCalculator } from "./crc";

const viewMap = new WeakMap<ArrayBuffer, DataView>();

function getDataView(buffer:ArrayBuffer){
  let dataview=viewMap.get(buffer);
  if(!dataview){
    dataview=new DataView(buffer);
    viewMap.set(buffer,dataview);
  }
  return dataview;
}
export function writeByte8(
  buffer: ArrayBuffer,
  UInt8: Array<number>,
  offset: number = 0
) {
 
  const dataview = getDataView(buffer);
  for (let i = 0; i < UInt8.length; i++) {
    dataview.setUint8(offset + i, UInt8[i]);
  }
  return dataview;
}
export function writeByte16(
  buffer: ArrayBuffer,
  UInt8: Array<number>,
  offset: number = 0
) {
  const dataview = getDataView(buffer);
  for (let i = 0; i < UInt8.length; i++) {
    dataview.setUint16(offset + i, UInt8[i]);
  }
  return dataview;
}

export function readByte8(buffer: ArrayBuffer, offset: number) {
  const view = getDataView(buffer);
  return view.getUint8(offset);
}

export function packChunk(type: number, data?: ArrayBuffer) {
  const length = data ? data.byteLength : 0;
  let dataView: DataView | undefined;
  if (data) dataView = getDataView(data);
  const buffer = new ArrayBuffer(length + 12);
  const view = getDataView(buffer);
  view.setUint32(0, length);
  view.setUint32(4, type);
  if (dataView) {
    for (let i = 8; i < length + 8; i++) {
      view.setUint8(i, dataView.getUint8(i - 8));
    }
  }
  const crc = CrcCalculator.crc32(buffer.slice(4, buffer.byteLength - 4));
  view.setUint32(length + 8, crc);
  return buffer;
}
